var ChatMsg = (function(){
    /**
     * 消息体类. 
     */
    var _chatMsgTmp = [
        '<div class="chatMsgItem <%=o? o.from : "web" %>" seq="<%=o.seq%>">', 
            '<div class="chatUserIcon hvBox">', 
                '<img class="chatUserIconImg" src="<%= (o.user && o.user.icon) ? ujs.browser.loc.addQuery(o.user.icon,{w:200}) : ujs.getConfigRes("defUserIcon") %>" />', 
            '</div>', 
            '<h4 class="chatUserName">',
                '<%= o.user.name %>',
            '</h4>', 
            '<div class="chatMsgItemContentWrapper">', 
                '<pre class="chatMsgItemContent">',
                    '<%= o.text ? o.text.trimEmptyTags().nl2br() : "" %>',                    
                '</pre>',
                '<div class="retry"></div>',
                '<div class="chatMsgTime">',
                    '<%= Date.getTimeTooltip(o.createTime) %>',
                '</div>',
                '<span class="showReaders">.....</span>', 
                '<div class="sendProgressBar">',
                    '<button style="z-index: 9999999999999;position: absolute;background: #ccc;bottom: 15px;right: 5px;letter-spacing: 1px;border-radius: 3px;padding: 3px;cursor: pointer;">Cancel</button>',
                '</div>',
            '</div>', 
        '</div>'
    ].join('');
    
    var _chatMsg = function ChatMsg(msg, pos){
        var _this = this;
        Observable.enable(this);
        this.rawMsg = msg || {};
        
        //默认消息发送者为当前用户.        
        Object.dft(this.rawMsg, 'user', ujs.util.session.getCurrentUserInfo());
        //设置消息发送者默认头像.
        Object.dft(this.rawMsg['user'], 'icon', ujs.getConfigRes('defUserIcon'));
        
        this.pos = pos;
        
        //处理Msg DataAdapter.
        var msgDataAdapterConstructor = null;
        try{           
            var msgAdapterName = this.constructor.name.replace('Chat', '') + 'DataAdapter';            
            msgDataAdapterConstructor = eval(msgAdapterName);            
        }catch(e){
            
        }
        
        if(msgDataAdapterConstructor){
            this.dataAdapter = new (msgDataAdapterConstructor)();            
        }
         
        //显示读者.
        this.on('showReaders', function($showReaders, seq){            
            page.biz.getMsgReaders(ChatPanel.getActiveChatPanel().chatGroupEntity['id'], seq, function(msg){
                var readers = msg['readers'];
                if(!readers.length){
                    return bubble.msg(lan('app.im.chat.reader.noReader'));
                }
                var $wrapper = _this.$wrapper.find('.chatMsgItemContentWrapper');
                var pos = $showReaders.offset();
                $(tmpl(ChatPanelView.readerList, readers || {})).appendTo(document.body).css({
                    left : _this.$wrapper.hasClass('right') ? pos.left - 30 :  pos.left,
                    top : pos.top + 15
                });
            });                
        });            
        this.isInit = false;        
    };
    
    _chatMsg.prototype._init = function(){};
    
    _chatMsg.prototype.render = function (chatView, relMsg, pos, relpos) {        
        var _this = this;
        this.chatView = chatView;
        this.chatGroupID = chatView.chatPanel.chatGroupEntity['id'];
                
        if(!this.isInit){        
            this.msg = this.dataAdapter ? this.dataAdapter.parse(this.rawMsg) : this.rawMsg;
            this.$wrapper = $(tmpl(_chatMsgTmp, this.msg || {}));
            this.$retryBtn = this.$wrapper.find('.retry');
            
            this.$sendProgressBar = this.$wrapper.find('.sendProgressBar');
            
            if(this.pos === 'right'){
                this.$wrapper.addClass('right');
            }
            this._init();  
            
            if(this.chatView.chatPanel.mode == 'view'){
                this.$wrapper.find('.showReaders').hide();
                this.setReaded();
            } else {  
                this.$wrapper.find('.showReaders').click(function(){
                    $('.readerListWrapper').remove();
                    _this.fire('showReaders', $(this), parseInt(_this.$wrapper.attr('seq')));
                    return false;
                });
            }
                              
            if(this.msg['lat'] < 500 && this.msg['lng'] < 500){
                var $posIcon = $('<img class="mapPin" src="/ujs/app/im/images/marker/16.png" />');
                this.$wrapper.find('.chatMsgItemContentWrapper').prepend($posIcon);
                $posIcon.click((function(lat, lng){
                    return function(){                        
                        ujs.ui.Dialog.get(ShareLocDialog, {
                            loc : {
                                latitude : lat,
                                longitude : lng
                            },
                            bodyStyle : 'margin:0px',
                            toolbar : false
                        });                            
                    };
                })(this.msg['lat'], this.msg['lng']));
            }
                  
            var chatGroupPerm = _this.chatView.chatPanel.chatGroupEntity.perm;
            if(!ujs.util.session.isCurrentUser(_this.rawMsg['user']) && ChatGroupPerm.check(chatGroupPerm, ChatGroupPerm.PARTICIPANTPROFILE)){
                this.$wrapper.find('.chatUserIcon').css('cursor', 'pointer').click(function(){ 
                    var uid = _this.rawMsg['user']['id'];
                    var isLocationAlertChat = ChatPanel.isActiveLocationAlert(_this.chatGroupID);
                    
                    var markers = _this.chatView.chatPanel.markers;
                    if(isLocationAlertChat && markers && markers[uid]){
                        var marker = markers[uid];
                        _this.chatView.chatPanel.map.setCenter(marker.position);  
                        Object.each(_this.chatView.chatPanel.markers, function(userID, userMarker){
                            if(userMarker){
                                if(uid == userID){
                                    userMarker.infoWindow.open(_this.chatView.chatPanel.map, userMarker);
                                } else {
                                    userMarker.infoWindow.close();
                                }
                            }
                        });
                    } else {               
                        ujs.ui.Dialog.get( UserProfileViewerDialog ,{
                            title : lan('dialog.title.detail'),
                            user : _this.rawMsg['user'],
                            perm : chatGroupPerm 
                        });
                    }
                });
            }
            
            //若是singleChat,隐藏showReaders.
            var chatGroupEntity = page.chatGroupStore.getItem(this.chatGroupID); 
            if(!chatGroupEntity || chatGroupEntity['type'] === ChatGroupType.SINGLECHAT){
                this.disableShowReaders();
            } else {
                this.setReaded();
            }
            //非当前用户不显示showReader按钮.
            if(!ujs.util.session.isCurrentUser(this.msg['user'])){
                this.disableShowReaders();
            }
                       
            if(this.chatView.chatPanel.keys){
                var m = new ujs.ui.CommonHighlighter();
                m.mark(this.chatView.chatPanel.keys.join(' '), this.$wrapper.get(0));
            }
                       
            this.isInit = true;
        }
        chatView.addMsg(this, relMsg, pos, relpos);
        return this;
    };
    
    //-----------------------进度条控制-------------------------------------
    
    _chatMsg.prototype.showProgressBar = function(){
        this.$sendProgressBar.show();
        this.fire('showProgressBar', this);
        return this;
    };    
    _chatMsg.prototype.hideProgressBar = function(){
        this.$sendProgressBar.hide();
        return this;
    };
    
    //---------------------------已读/未读控制------------------------------
    
    _chatMsg.prototype.setUnread = function(){
        this.$wrapper.find('.chatMsgItemContentWrapper').addClass('unread');
    };
    
    _chatMsg.prototype.setReaded = function(){
        var $read = this.$wrapper.find('.chatMsgItemContentWrapper').removeClass('unread');
        if(this.chatView.chatPanel.chatGroupEntity.type === 'singlechat'){
            $read.addClass('read');
        }
    };
    
    //-----------------------showReaders按钮控制----------------------------
    
    _chatMsg.prototype.enableShowReaders = function(){
        this.$wrapper.find('.showReaders').show();
    };
    
    _chatMsg.prototype.disableShowReaders = function(){
        this.$wrapper.find('.showReaders').hide();
    };
    
    _chatMsg.prototype.canShowReaders = function(){
        return this.$wrapper.find('.showReaders').is(':visible');
    };
    
    //----------------------------------------------------------------------
    
    _chatMsg.prototype.updateSeq = function(seq){
        this.$wrapper.attr('seq', seq);
        return this;
    };
    
    _chatMsg.prototype.updateMsgTime = function(time){
        this.$wrapper.find('.chatMsgTime').text(Date.getTimeTooltip(time));
        return this;
    };
    
    //----------------------------------------------------------------------
    
    _chatMsg.prototype.show = function(){
        this.$wrapper.show();
    };
        
    _chatMsg.prototype.hide = function(){
        this.$wrapper.hide();
    };
    
    //----------------------------------------------------------------------
    
    _chatMsg.prototype.markFailed = function(){        
        this.$wrapper.removeClass('sending').addClass('fail');
    };
    
    _chatMsg.prototype.markSending = function(){        
        this.$wrapper.removeClass('fail').addClass('sending');
    };
    
    _chatMsg.prototype.clearSending = function(){        
        this.$wrapper.removeClass('sending').removeClass('fail');
    };
    
    _chatMsg.prototype.adjustPos = function(seq){
        var currentSeq = seq || parseInt(this.$wrapper.attr('seq'));
        var $nextMsges = this.$wrapper.nextAll('.chatMsgItem:not(.sending, .fail)');
        for(var i = $nextMsges.length-1; i > -1; i--){
            var $msg = $($nextMsges.get(i)); 
            if(parseInt($msg.attr('seq')) < currentSeq){
                $msg.after(this.$wrapper);
                break;
            }    
        }
        return this;
    };
    
    //------------------------------------------------------------------------
    
    /**
     * 获取消息的文本描述。 
     * @param {Object} msg
     */
    _chatMsg.getMsgDesp = function(msg){
        var msgType = msg['contentType'] || msg['msgType'] || msg['msgtype']; 
        if(msgType === MsgType.IMAGE){
            return lan('app.im.msg.img');
        }
        if(msgType === MsgType.FILE){
            return lan('app.im.msg.file');
        }
        if(msgType === MsgType.AUDIO){
            return lan('app.im.msg.audio');
        }
        if(msgType === MsgType.VIDEO){
            return lan('app.im.msg.video');
        }
        if(msgType === MsgType.LOCATION){
            return lan('app.im.msg.loc');
        }
        if(msgType === MsgType.STICKER){
            return lan('app.im.msg.sticker');
        }
        if(msgType === MsgType.CONTACT){
            return lan('app.im.msg.contact');
        }        
        return msg['content'];
    };
    
    return _chatMsg;
})();